package com.sparrow.resource.global;

import com.sparrow.resource.annotation.InjectGlobalValue;
import com.sparrow.resource.convert.ValueConverter;
import com.sparrow.resource.cache.ResourceCache;
import com.sparrow.resource.service.ResourceService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;

/**
 *  全局配置注入处理器
 */
@Component
public class GlobalValueInjectProcessor implements BeanPostProcessor {

    @Autowired
    private ResourceService resourceService;

    private Set<Object> cacheSet = new HashSet<>();

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        injectFieldValue(bean);
        return bean;
    }

    public void injectFieldValue(Object bean) {
        ResourceCache<String, ? extends IGlobalItem> globalResCache = resourceService.getGlobalResourceCache();
        Class<?> clazz = bean.getClass();
        boolean inject = false;
        for (Field field : clazz.getDeclaredFields()) {
            InjectGlobalValue annotation = field.getAnnotation(InjectGlobalValue.class);
            if (annotation == null) {
                continue;
            }
            inject = true;
            String key = annotation.value();
            IGlobalItem item = globalResCache.getResource(key);
            String value = item.getValue();
            if (value != null) {
                field.setAccessible(true);
                try {
                    String typeStr = ValueConverter.mapFieldType(field);
                    Object convertedValue = ValueConverter.convertVal("", value, typeStr, field);
                    field.set(bean, convertedValue);
                } catch (IllegalAccessException e) {
                    throw new BeansException("注入失败：" + field, e) {};
                }
            }
        }

        if (inject) {
            cacheSet.add(bean);
        }
    }

    public void reInjectAll() {
        for (Object obj : cacheSet) {
            injectFieldValue(obj);
        }
    }
}

